"""

Defines a class :class:`Project` used to simplify the management of 
multiple Django applications on a WSGI host.
The advantage is that you have a central place to define 
your DJANGO_SETTINGS_MODULE    


Usage:

In your project dicrectory, create a file named 
:file:`django_project.py` containing at least something 
like this::

    self.update(django_settings_module='lino.demo.cosi.settings')
    self.update(hostname='example.com')
  
Now you can replace the content of all your `manage.py` files 
with the following::    
    
    __import__('garden').Project(__file__).manage()

And your `wsgi.py` by :: 

    application = __import__('garden').Project(__file__).get_wsgi_application()
    
    
Tests:

>>> from garden import Project
>>> p = Project()


Usage:

Create a file :file:`/etc/garden/config.py` with something 
like this::

    Garden.virtualenv_root = '/usr/local/pythonenv'
    Garden.default_python_version = '2.6'
    Garden.local_pythonpath = '/home/luc/mypy'
    Garden.DEBUG=False

    Garden.register_venv('demo','2.6')
    Garden.register_venv('prod','2.6')
    Garden.register_venv('test','2.6')
    
    Garden.projects_root = '/home/luc/mypy/lino_local'
    Garden.settings_prefix = 'local_lino'
    Garden.register_project('dsbe','demo')
    Garden.register_project('cosi','demo')


Then for each Django project on your host you can use the 
same files :file:`manage.py` and :file:`wsgi.py`::

manage.py::

    #!/usr/bin/env python
    if __name__ == "__main__":
        from atelier.djangoconf import manage
        manage(__file__ [,...] )

  

:copyright: Copyright 2013 by Luc Saffre.
:license: BSD, see LICENSE for more details.

"""

from os.path import split, dirname, abspath, join
execfile(join(dirname(__file__),'setup_info.py'))
__version__ = SETUP_INFO['version'] 

#~ from garden.projects import Project

import os
import sys
import site

APACHE_CONF_TEMPLATE = """\
<VirtualHost *:80>
  ServerName %(project_name)s.%(hostname)s
  ServerAdmin webmaster@%(hostname)s

  WSGIDaemonProcess %(project_name)s processes=2 threads=15
  WSGIProcessGroup %(project_name)s
  WSGIScriptAlias / %(project_dir)s/wsgi.py
  WSGIApplicationGroup %{GLOBAL}

  Alias /media/ %(project_dir)s/media/
  <Location /media/>
     SetHandler none
  </Location>

  ErrorLog ${APACHE_LOG_DIR}/error.log

  # Possible values include: debug, info, notice, warn, error, crit,
  # alert, emerg.
  LogLevel warn

  CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>
""" 


class VirtualEnv(object):
    def __init__(self,garden,name,python_version=None):
        self.name = name
        self.python_version = python_version or garden.default_python_version
        
        
class Project(object):
    project_name = None
    hostname = None
    django_settings_module = 'settings'
    
    def __init__(self,name,project_dir,**kw):
        self.project_name = name
        self.project_dir = project_dir
        #~ self.project_name = p.name
        #~ filename = self.project_dir.child('django_project.py')
        #~ if filename.exists():
            #~ context = dict(self=self)
            #~ execfile(filename,context)
            
        for k,v in kw.items():
            if not hasattr(self,k):
                raise Exception("Unkonwn attribute %s" % k)
            setattr(self,k,v)
            
    def configure(self): #,filename,virtual_env=DEFAULT_VIRTUALENV,settings_module=None,prefix='demo_sites.'):
        """
        :filename: Usually calling code gives `__file__` here.
        :virtual_env: The virtual environment to use
        
        """
        os.environ['DJANGO_SETTINGS_MODULE'] = self.django_settings_module
        
        #~ filename = globals_dict['__file__']
        if self.site_packages_path:
            site.addsitedir(self.site_packages_path)
        
        if self.local_pythonpath:
            sys.path.append(self.local_pythonpath)

            
            
    def manage(self):
        self.configure()
        from django.core.management import execute_from_command_line
        execute_from_command_line(sys.argv)
        
    def get_wsgi_application(self):
        os.environ['DJANGO_SETTINGS_MODULE'] = self.django_settings_module
        from django.core.wsgi import get_wsgi_application
        return get_wsgi_application()
        
    def get_apache_conf(self):
        context = dict(project_name=self.project_name,hostname=self.hostname)
        context.update(project_dir=self.project_dir)
        return APACHE_CONF_TEMPLATE % context
        

        


class Garden(object):
    virtual_envs = dict()
    django_projects = dict()
    django_projects_paths = dict()
    projects_root = None
    virtualenv_root = '/usr/local/pythonenv'
    default_python_version = '2.6'
    local_pythonpath = None
    last_virtual_env = None
    settings_prefix = ''
    DEBUG = False

    @classmethod
    def register_venv(self,name,*args,**kw):
        if self.virtual_envs.has_key(name):
            raise Exception("Duplicate name %s" % name)
        e = VirtualEnv(self,name,*args,**kw)
        self.virtual_envs[name] = e
        self.last_virtual_env = e

    @classmethod
    def register_project(self,name,virtual_env=None,settings_module=None,**kw):
        if self.django_projects.has_key(name):
            raise Exception("Duplicate name %s" % name)
        project_dir = join(self.projects_root,name)    
        if settings_module is None:
            #~ prj = split(dirname(abspath(filename)))[-1]
            settings_module = self.settings_prefix + name + '.settings'
        kw.update(django_settings_module=settings_module)
        if virtual_env is None:
            e = self.last_virtual_env
        else:
            e = self.virtual_envs[virtual_env]
        kw.update(site_packages_path=join(
            self.virtualenv_root,'%s/lib/python2.6/site-packages' % (e.name,e.python_version)))

        p = Project(self,name,project_dir,**kw)
        self.django_projects[p.project_name] = p
        self.django_projects_paths[p.project_dir] = p

    @classmethod
    def summary(self,*cmdline_args):
        """Print a summary to stdout."""
        headers = (
          'path','project_name','hostname')

        def cells(prj):
            return [
                prj.project_dir,
                prj.project_name,
                prj.hostname]
            
        print rstgen.table(headers,[cells(Project(p)) for p in env.django_projects])
    

config_file = '/etc/garden/config.py'

if os.path.exists(config_file):
    context = dict(Garden=Garden)
    execfile(config_file,context)


def find_project(filename):
    return Garden.django_projects_paths.get(dirname(filename))
    
